package com.myjpa.generate;

import lombok.Getter;
import lombok.Setter;

/**
 * @author: yaoll
 * @date: 2020-09-04
 * @verison: 1.0
 */
@Getter
@Setter
public class EntityGenerator {

	private StringBuilder buff;

	public void generate(GenerateContext ctx) {

		buff = new StringBuilder();
		buff.append("package " + ctx.getPkg() + ".entity;\n");
		buff.append("\n");
		buff.append("import lombok.Getter;").append("\n");
		buff.append("import lombok.Setter;").append("\n");
		buff.append("import ").append(ctx.getPkg()).append(".model.").append(ctx.getModelClass()).append(";\n");
		GenerateContext.PrimaryKey primaryKey = ctx.getPrimaryKey();
		if (primaryKey.getGenerationType() == GenerateContext.PrimaryKey.GENERATION_TYPE_ASSIGNED) {
			buff.append("import org.hibernate.annotations.GenericGenerator;\n");
			buff.append("import javax.persistence.GeneratedValue;\n");
		}

		buff.append("import javax.persistence.*;").append("\n");
		buff.append("import java.util.Date;").append("\n");
		buff.append("\n");
		buff.append("@Setter").append("\n");
		buff.append("@Getter").append("\n");
		buff.append("@Entity").append("\n");
		buff.append("@Table(name = \"" + ctx.getTableName() + "\")").append("\n");
		buff.append("public class " + ctx.getEntityClass() + " {").append("\n");
		buff.append("").append("\n");

		generatePrimaryKey(ctx, buff);

		for (Attribute att : ctx.getAtts()) {
			buff.append("\t").append("private ").append(att.getType().getSimpleName()).append(" ").append(att.getName()).append(";").append("\n");
		}
		buff.append("\n");

		generateFrom(ctx, buff);
		generateTo(ctx, buff);

		buff.append("}").append("\n");

	}

	private void generatePrimaryKey(GenerateContext ctx, StringBuilder buff) {
		GenerateContext.PrimaryKey primaryKey = ctx.getPrimaryKey();
		String generationType = primaryKey.getGenerationType();
		buff.append("\t").append("@Id").append("\n");
		if (GenerateContext.PrimaryKey.GENERATION_TYPE_IDENTITY.equals(generationType)) {
			buff.append("\t").append("@GeneratedValue(strategy = GenerationType.IDENTITY)").append("\n");
		} else if (GenerateContext.PrimaryKey.GENERATION_TYPE_ASSIGNED.equals(generationType)) {
			buff.append("\t").append("@GeneratedValue(generator = \"assignedId\")").append("\n");
			buff.append("\t").append("@GenericGenerator(name = \"assignedId\", strategy = \"assigned\")").append("\n");
		}
		buff.append("\t").append("private ").append(primaryKey.getType()).append(" ").append(primaryKey.getName()).append(";\n");
	}

	private void generateFrom(GenerateContext ctx, StringBuilder buff) {
		buff.append("\t").append("public static ").append(ctx.getEntityClass()).append(" fromModel(").append(ctx.getModelClass()).append(" model) {").append("\n");

		buff.append("\t\t").append(ctx.getEntityClass()).append(" entity = new ").append(ctx.getEntityClass()).append("();\n");

		GenerateContext.PrimaryKey primary = ctx.getPrimaryKey();
		if (primary != null) {
			String name = primary.getName();
			String tter = name.substring(0, 1).toUpperCase() + name.substring(1);
			buff.append("\t\t").append("entity.set").append(tter).append("(model.get").append(tter).append("());\n");
		}

		for (Attribute att : ctx.getAtts()) {
			buff.append("\t\t").append("entity.").append(att.getSetter()).append("(model.").append(att.getGetter()).append("());\n");
		}
		buff.append("\t\t").append("return entity;\n");
		buff.append("\t}\n");
		buff.append("\n");
	}

	private void generateTo(GenerateContext ctx, StringBuilder buff) {
		buff.append("\t").append("public ").append(ctx.getModelClass()).append(" toModel() {").append("\n");

		buff.append("\t\t").append(ctx.getModelClass()).append(" model = new ").append(ctx.getModelClass()).append("();\n");

		GenerateContext.PrimaryKey primary = ctx.getPrimaryKey();
		if (primary != null) {
			String name = primary.getName();
			buff.append("\t\t").append("model.set").append(name.substring(0, 1).toUpperCase() + name.substring(1)).append("(this.").append(name).append(");\n");
		}

		for (Attribute att : ctx.getAtts()) {
			buff.append("\t\t").append("model.").append(att.getSetter()).append("(this.").append(att.getGetter()).append("());\n");
		}
		buff.append("\t\t").append("return model;\n");
		buff.append("\t}\n");
		buff.append("\n");
	}

}
